#pragma once

/**
 * 用户使用muduo库编写服务器程序
 * 在此把所有需要的头文件都包含，否则用户使用要包含很多头文件
*/

#include "EventLoop.h"
#include "Acceptor.h"
#include "InetAddress.h"
#include "noncopyable.h"
#include "EventLoopThreadPoll.h"
#include "Callbacks.h"
#include "TcpConnection.h"
#include "Buffer.h"

#include <functional>
#include <string>
#include <memory>
#include <atomic>
#include <unordered_map>

// 服务器编程使用的类
class TcpServer : noncopyable
{
public:
    using ThreadInitCallback = std::function<void(EventLoop*)>;  // 线程初始化类型

    enum Option  // 对端口是否可重用
    {
        kNoReusePort,
        kReusePort,
    };

    TcpServer(EventLoop* loop, const InetAddress& listenAddr, const std::string& nameArg, Option option = kNoReusePort);
    ~TcpServer();

    const std::string& ipPort() const { return ipPort_; }
    const std::string& name() const { return name_; }
    EventLoop* getLoop() const { return loop_; }

    // 设置底层subloop的个数
    void setThreadNum(int numThreads);
    
    void setThreadInitCallback(const ThreadInitCallback& cb) { threadInitCallback_ = std::move(cb); }
    void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = std::move(cb); }
    void setMessageCallback(const MessageCallback& cb) { messageCallback_ = std::move(cb); }
    void setWriteCompleteCallback(const WriteCompleteCallback& cb) { writeCompleteCallback_ = std::move(cb); }

    // 开启服务器监听，实际上就是开启底层mainloop的accept的listen监听
    void start();
    
private:
    using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>;

    EventLoop* loop_;  // baseloop 用户定义的loop，传进来的

    const std::string ipPort_;  // 服务器ipPort
    const std::string name_;  // 服务器名称

    std::unique_ptr<Acceptor> acceptor_;  // 运行在mainloop，任务是监听新连接事件
    std::shared_ptr<EventLoopThreadPool> threadPool_;  // 事件循环线程池 one loop per thread

    ConnectionCallback connectionCallback_;  // 有新连接时的回调
    MessageCallback messageCallback_;  // 有读写消息时的回调
    WriteCompleteCallback writeCompleteCallback_;  // 消息发送完成后的回调
    
    ThreadInitCallback threadInitCallback_;  // loop线程初始化的回调
    std::atomic_int started_;

    int nextConnId_;
    ConnectionMap connections_;  // 保存所有的连接

    // 创建TcpConnection
    void newConnection(int sockfd, const InetAddress& peerAddr);

    void removeConnection(const TcpConnectionPtr& conn);

    void removeConnectionInLoop(const TcpConnectionPtr& conn);
};


